Support input shapes: (#331070)
authorMatthias Clasen <mclasen@redhat.com>
Mon, 20 Feb 2006 01:36:50 +0000 (01:36 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Mon, 20 Feb 2006 01:36:50 +0000 (01:36 +0000)
2006-02-19  Matthias Clasen  <mclasen@redhat.com>

Support input shapes:  (#331070)

* gdk/gdk.symbols:
* gdk/gdkdisplay.h:
* gdk/gdkwindow.h:
* gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes)
(gdk_display_supports_input_shapes): Functions to determine
if a display supports shaped windows or input shapes.

* gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region):
(gdk_window_input_shape_combine_mask):
(gdk_window_set_child_input_shapes):
(gdk_window_merge_child_input_shapes): Input shape versions
of the window shape API.

* gtk/gtk.symbols:
* gtk/gtkwidget.h:
* gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask):
New function to set an input shape on a widget.

ChangeLog
ChangeLog.pre-2-10
gdk/gdk.symbols
gdk/gdkdisplay.h
gdk/gdkwindow.h
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkwindow-x11.c
gtk/gtk.symbols
gtk/gtkwidget.c
gtk/gtkwidget.h

index 36569949736a99c0927f4495e619c26915e9a878..798bc43e93678be18a0bf592ac7bc4421cac4254 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2006-02-19  Matthias Clasen  <mclasen@redhat.com>
+
+       Support input shapes:  (#331070)
+       
+       * gdk/gdk.symbols: 
+       * gdk/gdkdisplay.h: 
+       * gdk/gdkwindow.h: 
+       * gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes) 
+       (gdk_display_supports_input_shapes): Functions to determine
+       if a display supports shaped windows or input shapes.
+
+       * gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region): 
+       (gdk_window_input_shape_combine_mask): 
+       (gdk_window_set_child_input_shapes): 
+       (gdk_window_merge_child_input_shapes): Input shape versions
+       of the window shape API.
+
+       * gtk/gtk.symbols: 
+       * gtk/gtkwidget.h: 
+       * gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask): 
+       New function to set an input shape on a widget.
+
 2006-02-19  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix
index 36569949736a99c0927f4495e619c26915e9a878..798bc43e93678be18a0bf592ac7bc4421cac4254 100644 (file)
@@ -1,3 +1,25 @@
+2006-02-19  Matthias Clasen  <mclasen@redhat.com>
+
+       Support input shapes:  (#331070)
+       
+       * gdk/gdk.symbols: 
+       * gdk/gdkdisplay.h: 
+       * gdk/gdkwindow.h: 
+       * gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes) 
+       (gdk_display_supports_input_shapes): Functions to determine
+       if a display supports shaped windows or input shapes.
+
+       * gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region): 
+       (gdk_window_input_shape_combine_mask): 
+       (gdk_window_set_child_input_shapes): 
+       (gdk_window_merge_child_input_shapes): Input shape versions
+       of the window shape API.
+
+       * gtk/gtk.symbols: 
+       * gtk/gtkwidget.h: 
+       * gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask): 
+       New function to set an input shape on a widget.
+
 2006-02-19  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix
index b9485e3584ca09c7c81e64e5b5cb3b22a72f57c6..c628388e0823d0fc6387ef0f124327b77b5d50a5 100644 (file)
@@ -460,6 +460,8 @@ gdk_display_request_selection_notification
 gdk_display_store_clipboard
 gdk_display_supports_clipboard_persistence
 gdk_display_supports_selection_notification
+gdk_display_supports_shapes
+gdk_display_supports_input_shapes
 #endif
 #endif
 
@@ -728,6 +730,8 @@ gdk_window_get_events
 gdk_window_set_events
 gdk_window_shape_combine_mask
 gdk_window_shape_combine_region
+gdk_window_input_shape_combine_mask
+gdk_window_input_shape_combine_region
 gdk_window_set_override_redirect
 gdk_window_set_accept_focus
 gdk_window_set_focus_on_map
@@ -751,6 +755,8 @@ gdk_window_set_decorations
 gdk_window_set_functions
 gdk_window_set_child_shapes
 gdk_window_merge_child_shapes
+gdk_window_set_child_input_shapes
+gdk_window_merge_child_input_shapes
 gdk_window_set_static_gravities
 gdk_window_begin_move_drag
 gdk_window_begin_resize_drag
index d00fa5b5b227db578263bfde72ca347e0c6c34fb..c627a085810e8be12f8636bd8549b845ae3a0844 100644 (file)
@@ -179,6 +179,9 @@ void     gdk_display_store_clipboard                (GdkDisplay *display,
                                                     GdkAtom    *targets,
                                                     gint        n_targets);
 
+gboolean gdk_display_supports_shapes           (GdkDisplay    *display);
+gboolean gdk_display_supports_input_shapes     (GdkDisplay    *display);
+
 G_END_DECLS
 
 #endif /* __GDK_DISPLAY_H__ */
index e7570ab78c6fba19152916c3fe7b67d65c1509c4..4ff4847e16b4172f65416c7f2f4968a2d9d5e9c6 100644 (file)
@@ -396,6 +396,18 @@ void gdk_window_set_child_shapes (GdkWindow *window);
  */
 void gdk_window_merge_child_shapes (GdkWindow *window);
 
+void gdk_window_input_shape_combine_mask   (GdkWindow *window,
+                                           GdkBitmap *mask,
+                                           gint       x,
+                                           gint       y);
+void gdk_window_input_shape_combine_region (GdkWindow *window,
+                                            GdkRegion *shape_region,
+                                            gint       offset_x,
+                                            gint       offset_y);
+void gdk_window_set_child_input_shapes     (GdkWindow *window);
+void gdk_window_merge_child_input_shapes   (GdkWindow *window);
+
+
 /*
  * Check if a window has been shown, and whether all its
  * parents up to a toplevel have been shown, respectively.
index 263d37ab5cffbe62bc384e9a38ac24d86200c61d..6821ca8480746b7ea9ab0bb8ba3e338daa92dc56 100644 (file)
 #include <X11/extensions/Xfixes.h>
 #endif
 
+#ifdef HAVE_SHAPE_EXT
+#include <X11/extensions/shape.h>
+#endif
+
+
 static void   gdk_display_x11_class_init         (GdkDisplayX11Class *class);
 static void   gdk_display_x11_dispose            (GObject            *object);
 static void   gdk_display_x11_finalize           (GObject            *object);
@@ -158,8 +163,9 @@ gdk_display_open (const gchar *display_name)
   XClassHint *class_hint;
   gulong pid;
   gint i;
-#ifdef HAVE_XFIXES
+#if defined(HAVE_XFIXES) || defined(HAVE_SHAPE_EXT)
   gint ignore;
+  gint maj, min;
 #endif
 
   xdisplay = XOpenDisplay (display_name);
@@ -224,7 +230,20 @@ gdk_display_open (const gchar *display_name)
     }
   else
 #endif
-  display_x11->have_xfixes = FALSE;
+    display_x11->have_xfixes = FALSE;
+
+  display_x11->have_shapes = FALSE;
+  display_x11->have_input_shapes = FALSE;
+#ifdef HAVE_SHAPE_EXT
+  if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &ignore, &ignore))
+    {
+      display_x11->have_shapes = TRUE;
+#ifdef ShapeInput            
+      if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
+       display_x11->have_input_shapes = (maj == 1 && min >= 1);
+#endif
+    }
+#endif
 
   if (_gdk_synchronize)
     XSynchronize (display_x11->xdisplay, True);
@@ -1237,5 +1256,40 @@ gdk_x11_display_get_user_time (GdkDisplay *display)
   return GDK_DISPLAY_X11 (display)->user_time;
 }
 
+/**
+ * gdk_display_supports_shapes:
+ * @display: a #GdkDisplay
+ *
+ * Returns %TRUE if gdk_window_shape_combine_mask() can
+ * be used to create shaped windows on @display.
+ *
+ * Returns: %TRUE if shaped windows are supported 
+ *
+ * Since: 2.10
+ */
+gboolean 
+gdk_display_supports_shapes (GdkDisplay *display)
+{
+  return GDK_DISPLAY_X11 (display)->have_shapes;
+}
+
+/**
+ * gdk_display_supports_input_shapes:
+ * @display: a #GdkDisplay
+ *
+ * Returns %TRUE if gdk_window_input_shape_combine_mask() can
+ * be used to modify the input shape of windows on @display.
+ *
+ * Returns: %TRUE if windows with modified input shape are supported 
+ *
+ * Since: 2.10
+ */
+gboolean 
+gdk_display_supports_input_shapes (GdkDisplay *display)
+{
+  return GDK_DISPLAY_X11 (display)->have_input_shapes;
+}
+
+
 #define __GDK_DISPLAY_X11_C__
 #include "gdkaliasdef.c"
index 374a345cf80e8b246065b48248a39eeb614817e9..59ffd53122b53632f15f26e2f9f21f4c83bf4cfe 100644 (file)
@@ -83,7 +83,6 @@ const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
 /* Forward declarations */
 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
                                                   gboolean    on);
-static gboolean gdk_window_have_shape_ext         (GdkDisplay *display);
 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
 static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
 static void     set_wm_name                       (GdkDisplay  *display,
@@ -3686,19 +3685,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-static gboolean
-gdk_window_have_shape_ext (GdkDisplay *display)
-{
-#ifdef HAVE_SHAPE_EXT
-  int ignore;
-
-  return XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display),
-                              &ignore, &ignore);
-#else
-  return 0;
-#endif  
-}
-
 #define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
 
 /*
@@ -3706,34 +3692,12 @@ gdk_window_have_shape_ext (GdkDisplay *display)
  * If not available, shaped windows will look
  * ugly, but programs still work.    Stefan Wille
  */
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- *
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
- *
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- * 
- **/
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
-                              GdkBitmap *mask,
-                              gint x, gint y)
+static void
+do_shape_combine_mask (GdkWindow *window,
+                      GdkBitmap *mask,
+                      gint       x, 
+                      gint       y,
+                      gint       shape)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap pixmap;
@@ -3753,13 +3717,15 @@ gdk_window_shape_combine_mask (GdkWindow *window,
       return;
     }
   
-  if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+  if (shape == ShapeBounding
+      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
     {
       if (mask)
        {
          pixmap = GDK_PIXMAP_XID (mask);
          
-         private->shaped = TRUE;
+         private->shaped = (shape == ShapeBounding);
        }
       else
        {
@@ -3772,7 +3738,7 @@ gdk_window_shape_combine_mask (GdkWindow *window,
       
       XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
                         GDK_WINDOW_XID (window),
-                        ShapeBounding,
+                        shape,
                         x, y,
                         pixmap,
                         ShapeSet);
@@ -3781,20 +3747,20 @@ gdk_window_shape_combine_mask (GdkWindow *window,
 }
 
 /**
- * gdk_window_shape_combine_region:
+ * gdk_window_shape_combine_mask:
  * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
  *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
  *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- * 
  * On the X11 platform, this uses an X server extension which is
  * widely available on most common platforms, but not available on
  * very old X servers, and occasionally the implementation will be
@@ -3805,11 +3771,56 @@ gdk_window_shape_combine_mask (GdkWindow *window,
  * 
  **/
 void
-gdk_window_shape_combine_region (GdkWindow *window,
-                                 GdkRegion *shape_region,
-                                 gint       offset_x,
-                                 gint       offset_y)
-{ 
+gdk_window_shape_combine_mask (GdkWindow *window,
+                              GdkBitmap *mask,
+                              gint       x, 
+                              gint       y)
+{
+  do_shape_combine_mask (window, mask, x, y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ * 
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+                                    GdkBitmap *mask,
+                                    gint       x,
+                                    gint       y)
+{
+#ifdef ShapeInput
+  do_shape_combine_mask (window, mask, x, y, ShapeInput);
+#endif
+}
+
+
+static void
+do_shape_combine_region (GdkWindow *window,
+                        GdkRegion *shape_region,
+                        gint       offset_x,
+                        gint       offset_y,
+                        gint       shape)
+{
   GdkWindowObject *private = (GdkWindowObject *)window;
   gint xoffset, yoffset;
   
@@ -3834,12 +3845,14 @@ gdk_window_shape_combine_region (GdkWindow *window,
       return;
     }
   
-  if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+  if (shape == ShapeBounding
+      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
     {
       gint n_rects = 0;
       XRectangle *xrects = NULL;
 
-      private->shaped = TRUE;
+      private->shaped = shape == ShapeBounding;
 
       _gdk_region_get_xrectangles (shape_region,
                                    0, 0,
@@ -3847,7 +3860,7 @@ gdk_window_shape_combine_region (GdkWindow *window,
       
       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
                                GDK_WINDOW_XID (window),
-                               ShapeBounding,
+                               shape,
                                offset_x, offset_y,
                                xrects, n_rects,
                                ShapeSet,
@@ -3858,6 +3871,73 @@ gdk_window_shape_combine_region (GdkWindow *window,
 #endif /* HAVE_SHAPE_EXT */
 }
 
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ * 
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ * 
+ **/
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+                                 GdkRegion *shape_region,
+                                 gint       offset_x,
+                                 gint       offset_y)
+{ 
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ * 
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_region (GdkWindow *window,
+                                      GdkRegion *shape_region,
+                                      gint       offset_x,
+                                      gint       offset_y)
+{
+#ifdef ShapeInput
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
+#endif
+}
+
 
 /**
  * gdk_window_set_override_redirect:
@@ -5120,7 +5200,8 @@ gdk_add_rectangles (Display           *disp,
 static void
 gdk_propagate_shapes (Display *disp,
                      Window   win,
-                     gboolean merge)
+                     gboolean merge,
+                     int      shape)
 {
   Window              rt, par, *list = NULL;
   gint                i, j, num = 0, num_rects = 0;
@@ -5225,7 +5306,7 @@ gdk_propagate_shapes (Display *disp,
       /* set the rects as the shape mask */
       if (rects)
        {
-         XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
+         XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
                                   ShapeSet, YXSorted);
          g_free (rects);
        }
@@ -5261,11 +5342,12 @@ gdk_window_set_child_shapes (GdkWindow *window)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  
 #ifdef HAVE_SHAPE_EXT
   if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), FALSE);
+                         GDK_WINDOW_XID (window), FALSE, ShapeBounding);
 #endif   
 }
 
@@ -5281,7 +5363,6 @@ gdk_window_set_child_shapes (GdkWindow *window)
  * This function is distinct from gdk_window_set_child_shapes()
  * because it includes @window's shape mask in the set of shapes to
  * be merged.
- * 
  **/
 void
 gdk_window_merge_child_shapes (GdkWindow *window)
@@ -5290,12 +5371,69 @@ gdk_window_merge_child_shapes (GdkWindow *window)
   
 #ifdef HAVE_SHAPE_EXT
   if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), TRUE, ShapeBounding);
+#endif   
+}
+
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_set_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), TRUE);
+                         GDK_WINDOW_XID (window), FALSE, ShapeInput);
+#endif
 #endif   
 }
 
+/**
+ * gdk_window_merge_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of 
+ * shapes to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_merge_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), TRUE, ShapeInput);
+#endif
+#endif   
+}
+
+
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
 {
index 55320eb749991d15a0f27d0fa743615a502fed8c..398c442d18d280a2c9de6ad9aae716eda67f4105 100644 (file)
@@ -3970,6 +3970,7 @@ gtk_widget_set_size_request
 gtk_widget_set_state
 gtk_widget_set_style
 gtk_widget_shape_combine_mask
+gtk_widget_input_shape_combine_mask
 gtk_widget_show
 gtk_widget_show_all
 gtk_widget_show_now
index 560c2696a714010107e4d3c88d0d6feaf48f3836..187028af15f49c8845da29df10807e5e7ad2e047 100644 (file)
@@ -250,6 +250,7 @@ static GQuark               quark_event_mask = 0;
 static GQuark          quark_extension_event_mode = 0;
 static GQuark          quark_parent_window = 0;
 static GQuark          quark_shape_info = 0;
+static GQuark          quark_input_shape_info = 0;
 static GQuark          quark_colormap = 0;
 static GQuark          quark_pango_context = 0;
 static GQuark          quark_rc_style = 0;
@@ -324,6 +325,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode");
   quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
   quark_shape_info = g_quark_from_static_string ("gtk-shape-info");
+  quark_input_shape_info = g_quark_from_static_string ("gtk-input-shape-info");
   quark_colormap = g_quark_from_static_string ("gtk-colormap");
   quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
   quark_rc_style = g_quark_from_static_string ("gtk-rc-style");
@@ -2352,6 +2354,13 @@ gtk_widget_realize (GtkWidget *widget)
                                         shape_info->offset_y);
        }
       
+      shape_info = g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info);
+      if (shape_info)
+       gdk_window_input_shape_combine_mask (widget->window,
+                                            shape_info->shape_mask,
+                                            shape_info->offset_x,
+                                            shape_info->offset_y);
+
       if (!GTK_WIDGET_NO_WINDOW (widget))
        {
          mode = gtk_widget_get_extension_events (widget);
@@ -2380,7 +2389,10 @@ gtk_widget_unrealize (GtkWidget *widget)
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
   if (GTK_WIDGET_HAS_SHAPE_MASK (widget))
-    gtk_widget_shape_combine_mask (widget, NULL, -1, -1);
+    gtk_widget_shape_combine_mask (widget, NULL, 0, 0);
+
+  if (g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info))
+    gtk_widget_input_shape_combine_mask (widget, NULL, 0, 0);
 
   if (GTK_WIDGET_REALIZED (widget))
     {
@@ -2792,8 +2804,6 @@ gtk_widget_queue_shallow_draw (GtkWidget *widget)
   GdkRectangle rect;
   GdkRegion *region;
   
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
   if (!GTK_WIDGET_REALIZED (widget))
     return;
 
@@ -3880,7 +3890,7 @@ static void
 gtk_widget_reparent_fixup_child (GtkWidget *widget,
                                 gpointer   client_data)
 {
-  g_return_if_fail (client_data != NULL);
+  g_assert (client_data != NULL);
   
   if (GTK_WIDGET_NO_WINDOW (widget))
     {
@@ -4636,8 +4646,6 @@ gtk_widget_reset_rc_style (GtkWidget *widget)
   GtkStyle *new_style = NULL;
   gboolean initial_emission;
   
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
   initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget);
 
   GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE);
@@ -5766,8 +5774,6 @@ gtk_widget_set_usize_internal (GtkWidget *widget,
   GtkWidgetAuxInfo *aux_info;
   gboolean changed = FALSE;
   
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  
   g_object_freeze_notify (G_OBJECT (widget));
 
   aux_info = _gtk_widget_get_aux_info (widget, TRUE);
@@ -5894,9 +5900,7 @@ gtk_widget_set_size_request (GtkWidget *widget,
  * gtk_widget_set_size_request(). To get the size a widget will
  * actually use, call gtk_widget_size_request() instead of
  * this function.
- * 
  **/
 void
 gtk_widget_get_size_request (GtkWidget *widget,
                              gint      *width,
@@ -5930,7 +5934,6 @@ gtk_widget_get_size_request (GtkWidget *widget,
  * mask. This function can't be used with #GTK_NO_WINDOW widgets;
  * to get events on those widgets, place them inside a #GtkEventBox
  * and receive events on the event box.
- * 
  **/
 void
 gtk_widget_set_events (GtkWidget *widget,
@@ -6745,7 +6748,7 @@ gtk_widget_finalize (GObject *object)
 static void
 gtk_widget_real_map (GtkWidget *widget)
 {
-  g_return_if_fail (GTK_WIDGET_REALIZED (widget) == TRUE);
+  g_assert (GTK_WIDGET_REALIZED (widget));
   
   if (!GTK_WIDGET_MAPPED (widget))
     {
@@ -6787,7 +6790,7 @@ gtk_widget_real_unmap (GtkWidget *widget)
 static void
 gtk_widget_real_realize (GtkWidget *widget)
 {
-  g_return_if_fail (GTK_WIDGET_NO_WINDOW (widget));
+  g_assert (GTK_WIDGET_NO_WINDOW (widget));
   
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
   if (widget->parent)
@@ -7046,8 +7049,8 @@ gtk_widget_shape_combine_mask (GtkWidget *widget,
       shape_info->offset_x = offset_x;
       shape_info->offset_y = offset_y;
       
-      /* set shape if widget has a gdk window allready.
-       * otherwise the shape is scheduled to be set by gtk_widget_realize.
+      /* set shape if widget has a gdk window already.
+       * otherwise the shape is scheduled to be set by gtk_widget_realize().
        */
       if (widget->window)
        gdk_window_shape_combine_mask (widget->window, shape_mask,
@@ -7055,6 +7058,59 @@ gtk_widget_shape_combine_mask (GtkWidget *widget,
     }
 }
 
+/**
+ * gtk_widget_input_shape_combine_mask: 
+ * @widget: a #GtkWidget.
+ * @shape_mask: shape to be added, or %NULL to remove an existing shape. 
+ * @offset_x: X position of shape mask with respect to @window.
+ * @offset_y: Y position of shape mask with respect to @window.
+ * 
+ * Sets an input shape for this widget's GDK window. This allows for
+ * windows which react to mouse click in a nonrectangular region, see 
+ * gdk_window_input_shape_combine_mask() for more information.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_widget_input_shape_combine_mask (GtkWidget *widget,
+                                    GdkBitmap *shape_mask,
+                                    gint       offset_x,
+                                    gint       offset_y)
+{
+  GtkWidgetShapeInfo* shape_info;
+  
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  /*  set_shape doesn't work on widgets without gdk window */
+  g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
+
+  if (!shape_mask)
+    {
+      if (widget->window)
+       gdk_window_input_shape_combine_mask (widget->window, NULL, 0, 0);
+      
+      g_object_set_qdata (G_OBJECT (widget), quark_input_shape_info, NULL);
+    }
+  else
+    {
+      shape_info = g_slice_new (GtkWidgetShapeInfo);
+      g_object_set_qdata_full (G_OBJECT (widget), quark_input_shape_info, 
+                              shape_info,
+                              (GDestroyNotify) gtk_widget_shape_info_destroy);
+      
+      shape_info->shape_mask = g_object_ref (shape_mask);
+      shape_info->offset_x = offset_x;
+      shape_info->offset_y = offset_y;
+      
+      /* set shape if widget has a gdk window already.
+       * otherwise the shape is scheduled to be set by gtk_widget_realize().
+       */
+      if (widget->window)
+       gdk_window_input_shape_combine_mask (widget->window, shape_mask,
+                                            offset_x, offset_y);
+    }
+}
+
+
 static void
 gtk_reset_shapes_recurse (GtkWidget *widget,
                          GdkWindow *window)
index 5dec5bdd54ba9b0205edec243872ca247eeb61cd..d161bbebb3a28ce0e814b32723414a58823d93f6 100644 (file)
@@ -744,6 +744,10 @@ void            gtk_widget_shape_combine_mask (GtkWidget *widget,
                                            GdkBitmap *shape_mask,
                                            gint       offset_x,
                                            gint       offset_y);
+void        gtk_widget_input_shape_combine_mask (GtkWidget *widget,
+                                                 GdkBitmap *shape_mask,
+                                                 gint       offset_x,
+                                                 gint       offset_y);
 
 /* internal function */
 void        gtk_widget_reset_shapes       (GtkWidget *widget);